//	COPYRIGHT (C) 1981 BY BOARD OF TRUSTEES,
//	LELAND STANFORD JUNIOR UNIVERSITY

MANIFEST $( LH = BYTE 18:18; RH = BYTE 18:0; WORDSIZE = 36 $);
STATIC $( NULL = NIL; LISTCELLS = NIL; SPARECELLS = NIL;
          NLISTLEFT = NIL $);

LET INITLISTS(CELLVEC,DIM) BE
 $(
 NULL:=@NULL BITOR [@NULL<<[WORDSIZE/2]];
 !CELLVEC:=@NULL;
 FOR I=1 TO DIM DO CELLVEC!I:=CELLVEC+I-1;
 SPARECELLS:=CELLVEC+DIM;
 NLISTLEFT:=DIM;
 DIM-:=DIM/20;
 LISTCELLS:=CELLVEC+DIM;
 RH&&![LISTCELLS+1]:=@NULL
 $);

LET CONS(X,Y) = VALOF
 $( LET ANS = LISTCELLS;
 IF LISTCELLS=@NULL DO
  TEST SPARECELLS=@NULL THEN SPACEFULL("LIST")
  OR
   $(
   SPACEALMOSTFULL("LIST");
   LISTCELLS:=SPARECELLS;
   ANS:=LISTCELLS;
   SPARECELLS:=@NULL
   $);
 LISTCELLS:=!LISTCELLS;
 LISTCELLS:=RH&&LISTCELLS;
 !ANS:=Y BITOR [X<<[WORDSIZE/2]];
 NLISTLEFT-:=1;
 RESULTIS ANS
 $);

LET UNCONS(X) = VALOF
 $( LET ANS = !X;
 NLISTLEFT+:=1;
 !X:=LISTCELLS;
 LISTCELLS:=X;
 RESULTIS RH&&ANS
 $);

LET CAR(X) = VALOF $( X:=!X; RESULTIS LH&&X $);

LET CDR(X) = VALOF $( X:=!X; RESULTIS RH&&X $);

LET FRPLACA(X,VAL) BE
 $( STATIC $( TEM = NIL $);
 TEM:=!X;
 LH&&TEM:=VAL;
 !X:=TEM
 $);

LET FRPLACD(X,VAL) BE
 $( STATIC $( TEM = NIL $);
 TEM:=!X;
 RH&&TEM:=VAL;
 !X:=TEM
 $);

LET REPLND2(X,CARV,CDRV) BE
 $( STATIC $( TEM = NIL $);
 TEM:=CDRV;
 LH&&TEM:=CARV;
 !X:=TEM
 $);

LET LISTOF(N,V) = VALOF
 $( LET TEM=@NULL;
 WHILE N>0 DO $( N-:=1; TEM:=CONS(V,TEM) $);
 RESULTIS TEM
 $);

LET LAST(X) = VALOF
 $( LET TAIL=!X;
 WHILE RH&&TAIL NE @NULL DO $( X:=RH&&TAIL; TAIL:=!X $);
 RESULTIS X
 $);

LET DREVERSE(LST) = VALOF
 $( LET RLST,TAIL,TEM=@NULL,NIL,NIL;
 WHILE LST NE @NULL DO
  $(
  TAIL:=!LST;
  TEM:=TAIL;
  RH&&TAIL:=RLST;
  !LST:=TAIL;
  RLST:=LST;
  LST:=RH&&TEM
  $);
 RESULTIS RLST
 $);

LET LIST(X0,X1,X2,X3,X4,X5,X6,X7,X8,X9,
         XA,XB,XC,XD,XE,XF,XG,XH,XI,XJ) = VALOF
 $( LET ANS,I=@NULL,NUMBARGS();
 WHILE I>0 DO $( I-:=1; ANS:=CONS([@X0]!I,ANS) $);
 RESULTIS ANS
 $);

LET LENGTH(LST) = VALOF
 $( LET N=0;
 WHILE LST NE @NULL DO $( N+:=1; LST:=!LST; LST:=RH&&LST $);
 RESULTIS N
 $);

LET UNLIST(LST) BE
 UNLESS LST=@NULL DO
  $(
  NLISTLEFT+:=LENGTH(LST);
  FRPLACD(LAST(LST),LISTCELLS);
  LISTCELLS:=LST
  $);

LET NCONC(LST1,LST2) = VALOF
 $(
 IF LST1=@NULL DO RESULTIS LST2;
 FRPLACD(LAST(LST1),LST2);
 RESULTIS LST1
 $);

LET NCONC1(LST,VAL) = VALOF
 $(
 IF LST=@NULL DO RESULTIS CONS(VAL,@NULL);
 FRPLACD(LAST(LST),CONS(VAL,@NULL))
 RESULTIS LST
 $);

LET ASSOC(VAL,LST) = VALOF
 $( LET TEM=NIL;
 WHILE LST NE @NULL DO
  $(
  LST:=!LST;
  TEM:=![LH&&LST];
  IF VAL=LH&&TEM DO RESULTIS LH&&LST;
  LST:=RH&&LST
  $);
 RESULTIS @NULL
 $);

LET FMEMB(VAL,LST) = VALOF
 $( LET TEM=NIL;
 WHILE LST NE @NULL DO
  $(
  TEM:=!LST;
  IF VAL=LH&&TEM DO RESULTIS LST;
  LST:=RH&&TEM
  $);
 RESULTIS @NULL
 $);

LET SASSOC(VAL,LST,EQFN) = VALOF
 $( LET TEM = NIL;
 WHILE LST NE @NULL DO
  $(
  LST:=!LST;
  TEM:=![LH&&LST];
  IF EQFN(VAL,LH&&TEM) DO RESULTIS LH&&LST;
  LST:=RH&&LST
  $);
 RESULTIS @NULL
 $);

LET SOME(LST,PRED) = VALOF
 $( LET TEM=NIL;
 WHILE LST NE @NULL DO
  $(
  TEM:=!LST;
  IF PRED(LH&&TEM) DO RESULTIS LST;
  LST:=RH&&TEM
  $);
 RESULTIS @NULL
 $);

LET LISTMAX(LST,FN) = VALOF
 $( LET MAXVAL,VAL=MINUSINF,NIL;
 WHILE LST NE @NULL DO
  $(
  LST:=!LST;
  VAL:=FN(LH&&LST);
  IF VAL>MAXVAL DO MAXVAL:=VAL;
  LST:=RH&&LST
  $);
 RESULTIS MAXVAL
 $);

LET MAP(LST,FN) BE
 WHILE LST NE @NULL DO $( FN(LST); LST:=!LST; LST:=RH&&LST $);

LET MAPC(LST,FN) BE
 WHILE LST NE @NULL DO $( LST:=!LST; FN(LH&&LST); LST:=RH&&LST $);

LET MAPLIST(LST,FN) = VALOF
 $( LET ANS=@NULL;
 WHILE LST NE @NULL DO
  $(
  ANS:=CONS(FN(LST),ANS);
  LST:=!LST;
  LST:=RH&&LST
  $);
 RESULTIS DREVERSE(ANS)
 $);

LET MAPCAR(LST,FN) = VALOF
 $( LET ANS=@NULL;
 WHILE LST NE @NULL DO
  $(
  LST:=!LST;
  ANS:=CONS(FN(LH&&LST),ANS);
  LST:=RH&&LST
  $);
 RESULTIS DREVERSE(ANS)
 $);

LET FETCH(PATH,X) = VALOF
 $(
 WHILE PATH NE 0 DO
  $(
  TEST [PATH BITAND 1]=0 THEN X:=CAR(X) OR X:=CDR(X);
  PATH:=PATH>>2
  $);
 RESULTIS X
 $);

LET REPLACE(PATH,X,VAL) BE
 $(
 WHILE [PATH BITAND #14] NE 0 DO
  $(
  TEST [PATH BITAND 1]=0 THEN X:=CAR(X) OR X:=CDR(X);
  PATH:=PATH>>2
  $);
 TEST [PATH BITAND 1]=0 THEN FRPLACA(X,VAL) OR FRPLACD(X,VAL)
 $);

LET CREATE0(REC,PATH) BE
 $(
 WHILE [PATH BITAND #14] NE 0 DO
  $(
  TEST [PATH BITAND 1]=0 THEN 
   $(
   IF CAR(REC)=@NULL DO FRPLACA(REC,CONS(@NULL,@NULL));
   REC:=CAR(REC)
   $)
  OR
   $(
   IF CDR(REC)=@NULL DO FRPLACD(REC,CONS(@NULL,@NULL));
   REC:=CDR(REC)
   $);
  PATH:=PATH>>2
  $)
 $);

LET CREATE(P0,P1,P2,P3,P4,P5,P6,P7,P8,P9,
           PA,PB,PC,PD,PE,PF,PG,PH,PI,PJ) = VALOF
 $( LET ANS,I=CONS(@NULL,@NULL),NUMBARGS();
 WHILE I>0 DO $( I-:=1; CREATE0(ANS,[@P0]!I) $);
 RESULTIS ANS
 $);

LET UNCREATE0(REC,PATH,DISCARDS) = VALOF
 $(
 WHILE [PATH BITAND #14] NE 0 DO
  $( LET TEM=NIL;
  TEST [PATH BITAND 1]=0 THEN
   $(
   TEM:=CAR(REC);
   IF FMEMB(TEM,DISCARDS)=@NULL DO DISCARDS:=CONS(TEM,DISCARDS);
   REC:=TEM
   $)
  OR
   $(
   TEM:=CDR(REC);
   IF FMEMB(TEM,DISCARDS)=@NULL DO DISCARDS:=CONS(TEM,DISCARDS);
   REC:=TEM
   $);
  PATH:=PATH>>2
  $);
 RESULTIS DISCARDS
 $);

LET UNCREATE(REC,P0,P1,P2,P3,P4,P5,P6,P7,P8,P9,
                 PA,PB,PC,PD,PE,PF,PG,PH,PI,PJ) BE
 $( LET DISCARDS,I=@NULL,NUMBARGS()-1;
 WHILE I>0 DO $( I-:=1 ; DISCARDS:=UNCREATE0(REC,[@P0]!I,DISCARDS) $);
 MAPC(DISCARDS,UNCONS);
 UNLIST(DISCARDS);
 UNCONS(REC)
 $);

LET DREMOVE(VAL,LST) = VALOF
 $( STATIC $( L = NIL; TAIL = NIL $);
 TAIL:=LST;
 LST:=CONS(@NULL,LST);
 L:=LST;
 WHILE TAIL NE @NULL DO
  TEST CAR(TAIL)=VAL THEN
   $(
   FRPLACD(L,CDR(TAIL));
   UNCONS(TAIL);
   TAIL:=CDR(L)
   $)
  OR $( L:=TAIL; TAIL:=CDR(TAIL) $);
 TAIL:=CDR(LST);
 UNCONS(LST);
 RESULTIS TAIL
 $);

LET PLIST(LST,PFN,INITSTR,TWEEN1,TWEEN2,FINSTR) BE
 $(
 OUTS(INITSTR);
 WHILE LST NE @NULL DO
  $(
  PFN(CAR(LST));
  IF CDR(LST) NE @NULL DO
   TEST CDR(CDR(LST))=@NULL THEN OUTS(TWEEN2) OR OUTS(TWEEN1);
  LST:=CDR(LST)
  $);
 OUTS(FINSTR)
 $);
